package com.sihai.ehr.service.impl;

import com.sihai.core.*;
import com.sihai.core.beans.BeanInject;
import com.sihai.ehr.model.biz.AuditingBase;
import com.sihai.ehr.model.biz.Duty;
import com.sihai.ehr.model.biz.EmployeeinfoWork;
import com.sihai.ehr.model.sys.Organization;
import com.sihai.ehr.model.sys.Role;
import com.sihai.ehr.model.sys.User;
import com.sihai.ehr.repository.AuditingRepository;
import com.sihai.ehr.service.UserService;
import com.sihai.ehr.utils.MD5Util;
import com.sihai.ehr.web.pojo.StaffSearchPojo;
import com.sihai.ehr.web.pojo.UserSetupPojo;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.List;


@Service("userService")
public class UserServiceImpl implements UserService {

    @Resource
    private DataAccessor dataAccessor;
    @Resource
    private AuditingRepository auditingRepository;

    @Override
    public void saveUser(User user) {
        user.setPassword(MD5Util.toMD5(user.getPassword())); //MD5加密
        dataAccessor.save(user);
    }

    @Override
    public LimitedList<UserSetupPojo> findUserByid(StaffSearchPojo search, final String state, Limit limit, Sorter sorter) {
        String hql = "select new com.sihai.ehr.web.pojo.UserSetupPojo(u.id,e.id,e.workNo,e.baseId.name,e.organization.fullName,e.duty.dutyName,u.loginName,u.loginTime) from EmployeeinfoWork e,User u where e.cancel='0' and e.baseId.state=? and e.baseId=u.employeeinfoBase ";
        LimitedList<UserSetupPojo> pojos;
        if (search == null) {
            pojos = dataAccessor.findByHql(UserSetupPojo.class, hql, new Object[]{state}, limit, sorter);
        }

        Organization organization = null;
        boolean isReadTopOrg = false;
        if (search.getDepartment() > 0) {
            try {
                organization = dataAccessor.get(Organization.class, search.getDepartment());
                if (organization.getTopOrganization() == null) {
                    isReadTopOrg = true;
                }
            } catch (Exception e) {
                return null;
            }
        }
        if (search.getDepartment() < 0) {
            pojos = dataAccessor.findByHql(UserSetupPojo.class, hql, new Object[]{state}, limit, sorter);
        } else if (search.getDuty() < 0) {
            pojos = dataAccessor.findByHql(UserSetupPojo.class,
                    hql + (isReadTopOrg ? "and (e.organization.topOrganization.id=" + search.getDepartment() + " or e.organization.id=?)" : " and e.organization.id=?"), new Object[]{state, search.getDepartment()}, limit, sorter);
        } else {
            pojos = dataAccessor.findByHql(UserSetupPojo.class,
                    hql + (isReadTopOrg ? "and (e.organization.topOrganization.id=" + search.getDepartment() + " or e.organization.id=?)" : " and e.organization.id=?") + " and e.duty.id=?",
                    new Object[]{state, search.getDepartment(), search.getDuty()}, limit,
                    sorter);
        }
        return pojos;
    }

    @Override
    public UserSetupPojo getUserById(Long id) {
        if (id != null) {
            String hql = "select new com.sihai.ehr.web.pojo.UserSetupPojo(u.id,b.name,u.loginName) from User u,EmployeeinfoBase b where u.employeeinfoBase=b.id and u.id=?";
            return dataAccessor.findByHql(UserSetupPojo.class, hql, new Object[]{id}, null, null).get(0);
        }
        return null;
    }

    @Override
    public String updateUser(final UserSetupPojo pojo) {
        if (pojo == null) {
            return null;
        }

        User user = dataAccessor.get(User.class, pojo.getUserId());
        if (user != null) {
            String oldPassword = user.getPassword();
            if (!oldPassword.equals(pojo.getPassword())) {
                return "wrong_password";
            }

            dataAccessor.batchUpdate(new QueryCreator() {
                @Override
                public Query createQuery(Session session) {
                    return session.createQuery(String.format(
                            "update User u set u.password =(%s) where u.id=(%s)",
                            pojo.getNewPassword(), pojo.getUserId()));
                }
            });
            return "success";
        }
        return "fail";
    }

    @Override
    public void removeUser(final String userIds) {
        dataAccessor.batchUpdate(new QueryCreator() {
            @Override
            public Query createQuery(Session session) {
                return session.createQuery(String.format(
                        "delete User u where u.id in (%s)", userIds));
            }
        });
    }

    @Override
    public LimitedList<User> findByTopOrganizations(Long organizationId, Limit limit, Sorter sorter) throws Exception{
        Assert.notNull(organizationId, "organization is required");
        return dataAccessor.findByHql(User.class, "from User u where u.work.organization.topOrganization.id = ? and u.work.baseId.state='1'", new Object[]{organizationId}, limit, sorter);
    }

    @Override
    public boolean isExistByUserName(String account) throws Exception {
        Assert.notNull(account, "account is required");
        List list = dataAccessor.findByHql(User.class, "select u.id from User u where u.loginName = ?", new Object[]{account}, null, null);
        return list != null && !list.isEmpty();
    }

    @Override
    public boolean isExistByWorkId(Long workid) throws Exception {
        Assert.notNull(workid, "workid is required");
        List list = dataAccessor.findByHql(User.class, "select u.id from User u where u.work.id = ?", new Object[]{workid}, null, null);
        return list != null && !list.isEmpty();
    }

    @Override
    public User getUser(Long id) {
        Assert.notNull(id, "user id is required");
        return dataAccessor.get(User.class, id);
    }

    @Override
    public User getByLoginName(final String loginName)throws Exception {
        Assert.notNull(loginName, "loginName is required");
        return dataAccessor.findUnique(User.class, new QueryCreator() {
            @Override
            public Query createQuery(Session session) {
                Query query = session.createQuery("from User u where u.loginName = :account");
                query.setParameter("account", loginName);
                return query;
            }
        });
    }

    @Override
    public List<com.sihai.ehr.model.sys.Resource> findUserAuthorities(Long userId)throws Exception {
        final User user = getUser(userId);
        Assert.notNull(userId, "user id is required");
        Role role = dataAccessor.findUnique(Role.class, new QueryCreator() {
            @Override
            public Query createQuery(Session session) {
                Query query = session.createQuery("from Role r where r.duty.id = :dutyId");
                query.setParameter("dutyId", user.getWork().getDuty().getId());
                return query;
            }
        });
        if(role == null){
            return null;
        }
        return role.getResources();
    }

    public Duty findUpDuty(Duty baseDuty, List<? extends AuditingBase> auditProcess, AuditingBase currentAuditNode){
        return auditingRepository.findUpDuty(baseDuty, auditProcess, currentAuditNode);
    }
}
